home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / go32 / exphdlr.c < prev    next >
C/C++ Source or Header  |  1994-08-04  |  39KB  |  1,371 lines

  1. /* This is file EXPHDLR.C */
  2. /*
  3. ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954
  4. **
  5. ** This file is distributed under the terms listed in the document
  6. ** "copying.dj", available from DJ Delorie at the address above.
  7. ** A copy of "copying.dj" should accompany this file; if not, a copy
  8. ** should be available from where this file was obtained.  This file
  9. ** may not be distributed without a verbatim copy of "copying.dj".
  10. **
  11. ** This file is distributed WITHOUT ANY WARRANTY; without even the implied
  12. ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  13. */
  14.  
  15. /* Modified for VCPI Implement by Y.Shibata Aug 5th 1991 */
  16. /* Modified for DPMI Implement by H.Tsubakimoto */
  17. /* Merged DPMI with V1.09+ C. Sandmann sandmann@clio.rice.edu */
  18. /* History:66,55 */
  19.  
  20. #include <process.h>
  21. #include <stdio.h>
  22. #include <dos.h>
  23. #include <sys/stat.h>
  24. #include <time.h>
  25. #include <errno.h>
  26. #include <fcntl.h>
  27. #include <string.h>
  28. #include <dir.h>
  29. #include <ctype.h>
  30. #include <io.h>
  31.  
  32. #include "gotypes.h"
  33. #include "gdt.h"
  34. #include "idt.h"
  35. #include "tss.h"
  36. #include "utils.h"
  37. #include "paging.h"
  38. #include "npx.h"
  39. #include "mono.h"
  40. #include "vcpi.h"
  41. #include "graphics.h"
  42. #include "dpmi.h"
  43. #include "extdebug.h"
  44. #include "vcpi.h"
  45. #include "ustat.h"
  46. #include "dpmisim.h"
  47. #include "dalloc.h"
  48. #include "valloc.h"
  49. #include "control.h"
  50.  
  51. extern void do_faulting_finish_message(int);
  52. extern int old_video_mode;
  53.  
  54. void segfault(word32 v)
  55. {
  56.   if (!using_external_debugger || (tss_ptr == &ed_tss))
  57.   {
  58.     if (peekb(0x40, 0x49) != old_video_mode)
  59.     {
  60.       _AX = old_video_mode;
  61.       geninterrupt(0x10);
  62.     }
  63.     fprintf(stderr, "Segmentation violation in pointer 0x%08lx at %x:%lx\n", v-ARENA, tss_ptr->tss_cs, tss_ptr->tss_eip);
  64.     do_faulting_finish_message(0);
  65.   }
  66.   tss_ptr->tss_irqn = 14; /* make it a segfault */
  67.   tss_ptr->tss_cr2 = v;
  68. }
  69.  
  70. #define CHECK_SEGFAULT(p) { \
  71.   if (!page_is_valid(p)) \
  72.   { \
  73.     segfault(p); \
  74.     return 1; \
  75.   } \
  76. }
  77.  
  78. extern int debug_mode;
  79.  
  80. extern unsigned int cdecl _openfd[];
  81. extern word32 far *graphics_pt;
  82. extern int ctrl_break_hit;
  83.  
  84. extern int was_user_int;
  85. extern word16 vcpi_installed;           /* VCPI Installed flag */
  86. word16 new_pic;                         /* current IRQ0 Vector */
  87. char transfer_buffer[4096];             /* must be near ptr for small model */
  88. word32 transfer_linear;
  89.  
  90. int in_hardware_interrupt = 0;
  91.  
  92. word8 old_master_lo=0x08;
  93. word8 hard_master_lo=0x08, hard_master_hi=0x0f;
  94. word8 hard_slave_lo=0x70,  hard_slave_hi=0x77;
  95.  
  96. word32 user_dta;
  97. static struct REGPACK r;
  98. static int in_graphics_mode=0;
  99. int ctrl_c_causes_break=1;
  100.  
  101. static int i_10(void), i_21(void), i_31(void), i_33(void), generic_handler(void), i_21_44(void);
  102. static int turbo_assist(void);
  103.  
  104. static word32 flmerge(word32 rf, word32 tf)
  105. {
  106.   return (rf & 0xcff) | (tf & 0xfffff300L);
  107. }
  108.  
  109. void static set_controller(int v)
  110. {
  111. /*  disable();  */
  112.   int oldmask = inportb(0x21);
  113.   outportb(0x20, 0x11);
  114.   outportb(0x21, v);
  115.   outportb(0x21, 4);
  116.   outportb(0x21, 1);
  117.   outportb(0x21, oldmask);
  118. /*  enable();  */
  119. }
  120.  
  121. static char cntrls_initted = 0;
  122. extern char vector_78h, vector_79h;
  123.  
  124. int find_empty_pic(void)
  125. {
  126.   static word8 try[] = { 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8, 0xf8, 0x68, 0x78 };
  127.   int i, j;
  128.   for (i=0; i<sizeof(try); i++)
  129.   {
  130.     char far * far * vec = (char far * far *)(0L+try[i]*4L);
  131.     for (j=1; j<8; j++)
  132.     {
  133.       if (vec[j] != vec[0])
  134.         goto not_empty;
  135.     }
  136. /*    printf("Empty = %d\n", try[i]); */
  137.     return try[i];
  138.     not_empty:;
  139.   }
  140.   return 0x78;
  141. }
  142.  
  143. extern int  far _ev_kbinter;            /* keyboard interrupt flag */
  144. extern void interrupt (* far _ev_oldkbint)(void);
  145. extern void interrupt _ev_keybdint(void);
  146. extern void interrupt (* far _ev_oldcriterr)(void);
  147. extern void interrupt _ev_criterr(void);
  148.  
  149. word32 saved_interrupt_table[256];
  150.  
  151. void init_controllers(void)
  152. {
  153.   if(cntrls_initted) return;
  154.   cntrls_initted = 1;
  155.  
  156.   movedata(0, 0, _DS, FP_OFF(saved_interrupt_table), 256*4);
  157.  
  158.   disable();
  159.  
  160.   if (vcpi_installed)
  161.   {
  162.     old_master_lo = vcpi_get_pic();
  163.     hard_slave_lo = vcpi_get_secpic();
  164. /*    printf("VCPI pics were m=%d s=%d\n", old_master_lo, hard_slave_lo); */
  165.     hard_slave_hi = hard_slave_lo + 7;
  166.   }
  167.   else if(!use_DPMI)
  168.   {
  169.     old_master_lo = 0x08;
  170.     hard_slave_lo = 0x70;
  171.     hard_slave_hi = 0x77;
  172.   }
  173.  
  174.   _ev_kbinter = 1;
  175.   _ev_oldkbint = getvect(8+1);     /* this is *NOT* old_master_lo - required */
  176.   setvect(8+1,_ev_keybdint);       /* so DV/X will work (it redirects) */
  177.   _ev_oldcriterr = getvect(0x24);  /* critical error handler can't read kb */
  178.   setvect(0x24,_ev_criterr);       /* so we force failure if events active */
  179.  
  180.   if(use_DPMI)
  181.   {
  182.     enable();
  183.     return;
  184.   }
  185.  
  186.   if (old_master_lo == 0x08)
  187.   {
  188.     hard_master_lo = find_empty_pic();
  189.     if (vcpi_installed)
  190.       vcpi_set_pics(hard_master_lo, hard_slave_lo);
  191.     set_controller(hard_master_lo);
  192.     movedata(0, 0x08*4, 0, hard_master_lo*4, 0x08*4);
  193.   }
  194.   else
  195.   {
  196.     hard_master_lo = old_master_lo;
  197.   }
  198.   hard_master_hi = hard_master_lo + 7;
  199.  
  200.   enable();
  201.   vector_78h = hard_master_lo;
  202.   vector_79h = hard_master_lo + 1;
  203. }
  204.  
  205. void uninit_controllers(void)
  206. {
  207.   if(!cntrls_initted) return;
  208.   cntrls_initted = 0;
  209.   disable();
  210.  
  211.   movedata(_DS, FP_OFF(saved_interrupt_table), 0, 0, 256*4);
  212.  
  213.   if (old_master_lo == 0x08 && !use_DPMI)
  214.   {
  215.     if (vcpi_installed)
  216.       vcpi_set_pics(0x08, hard_slave_lo);
  217.     set_controller(0x08);
  218.   }
  219.   setvect(8+1,_ev_oldkbint);  /* not old_master_lo for XDV */
  220.   enable();
  221. }
  222.  
  223. static DPMIaddress exceptions[17];
  224. static DPMIaddress interrupt10;
  225. static DPMIaddress interrupt21;
  226. static DPMIaddress interrupt33;
  227. static DPMIaddress interrupt75;
  228.  
  229. void setDPMIvector(void)
  230. {
  231.   int i;
  232.   for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i) {
  233.     DPMIehandler(i, &exceptions[i]);
  234.     DPMIchangeException(i, &exceptions[i]);
  235.   }
  236.   DPMIhandler(0x10, &interrupt10);
  237.   DPMIchangeInterrupt(0x10, &interrupt10);
  238.   DPMIhandler(0x21, &interrupt21);
  239.   DPMIchangeInterrupt(0x21, &interrupt21);
  240.   DPMIhandler(0x33, &interrupt33);
  241.   DPMIchangeInterrupt(0x33, &interrupt33);
  242.   DPMIhandlerNPX(&interrupt75);
  243.   DPMIchangeInterrupt(0x75, &interrupt75);
  244. }
  245.  
  246. void restoreDPMIvector(void)
  247. {
  248.   int i;
  249.   for (i = 0; i < sizeof(exceptions) / sizeof(*exceptions); ++i)
  250.     DPMIchangeException(i, &exceptions[i]);
  251.   DPMIchangeInterrupt(0x10, &interrupt10);
  252.   DPMIchangeInterrupt(0x21, &interrupt21);
  253.   DPMIchangeInterrupt(0x33, &interrupt33);
  254.   DPMIchangeInterrupt(0x75, &interrupt75);
  255. }
  256.  
  257. void tss2reg(struct REGPACK *r)
  258. {
  259.   r->r_ax = (word16)(tss_ptr->tss_eax);
  260.   r->r_bx = (word16)(tss_ptr->tss_ebx);
  261.   r->r_cx = (word16)(tss_ptr->tss_ecx);
  262.   r->r_dx = (word16)(tss_ptr->tss_edx);
  263.   r->r_si = (word16)(tss_ptr->tss_esi);
  264.   r->r_di = (word16)(tss_ptr->tss_edi);
  265.   r->r_flags = (word16)(tss_ptr->tss_eflags);
  266.   r->r_ds = r->r_es = _DS;
  267. }
  268.  
  269. void reg2tss(struct REGPACK *r)
  270. {
  271.   tss_ptr->tss_eax = r->r_ax;
  272.   tss_ptr->tss_ebx = r->r_bx;
  273.   tss_ptr->tss_ecx = r->r_cx;
  274.   tss_ptr->tss_edx = r->r_dx;
  275.   tss_ptr->tss_esi = r->r_si;
  276.   tss_ptr->tss_edi = r->r_di;
  277.   tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
  278. }
  279.  
  280. /* The following routine should be used for _unsupported_ interrupt reflection
  281.  * to real mode for go32. For any inrerrupts not directly handled by go32,
  282.  * the return registers should _not_ be signed extended to fit the 32 bit
  283.  * extended registers, but should ensure that the high order words are
  284.  * preserved across the interrupt (this is how other extenders like DOS/4GW
  285.  * and X32-VM do it). If you are calling the interrupt from int86() this is
  286.  * not a problem, but if you do it from assembly code then it is ;-)
  287.  */
  288.  
  289. void reg2tss_short(struct REGPACK *r)
  290. {
  291.   (short)tss_ptr->tss_eax = r->r_ax;
  292.   (short)tss_ptr->tss_ebx = r->r_bx;
  293.   (short)tss_ptr->tss_ecx = r->r_cx;
  294.   (short)tss_ptr->tss_edx = r->r_dx;
  295.   (short)tss_ptr->tss_esi = r->r_si;
  296.   (short)tss_ptr->tss_edi = r->r_di;
  297.   tss_ptr->tss_eflags = flmerge(r->r_flags, tss_ptr->tss_eflags);
  298. }
  299.  
  300. extern int ctrl_c_flag;
  301.  
  302. int double_fault(void)
  303. {
  304.   fprintf(stderr, "double fault!\n");
  305.   exit(1);
  306.   return 1;
  307. }
  308.  
  309. int check_nonpresent_387(void )
  310. {
  311.   if (!using_external_debugger)
  312.   {
  313.     fprintf(stderr, "Fatal!  Application attempted to use not-present 80387!\n");
  314.     fprintf(stderr, "Floating point opcode at virtual address 0x%08lx\n", tss_ptr->tss_eip);
  315.   }
  316.   return 1;
  317. }
  318.  
  319. int unsupported_int()
  320. {
  321.   if (!debug_mode)
  322.     fprintf(stderr, "Unsupported INT 0x%02x\n", tss_ptr->tss_irqn);
  323.   return 1;
  324. }
  325.  
  326. #define U unsupported_int
  327. typedef int (*FUNC)(void);
  328. static FUNC exception_handler_list[] = {
  329.   U, U, U, U, U, U, U,
  330.   /* 07 */ check_nonpresent_387,
  331.   /* 08 */ double_fault,
  332.   U, U, U, U, U,
  333.   /* 0e */ page_in,
  334.   U,
  335.   /* 10 */ i_10,        /* Video Interrupt */
  336.   /* 11 */ generic_handler,    /* Equipment detection */
  337.   /* 12 */ generic_handler,    /* Get memory size (outdated) */
  338.   U,
  339.   /* 14 */ generic_handler,    /* Serial communication */
  340.   /* 15 */ generic_handler,    /* Lots of strange things */
  341.   /* 16 */ generic_handler,    /* Keyboard */
  342.   /* 17 */ generic_handler,    /* Parallel printer */
  343.   U, U,
  344.   /* 1a */ generic_handler,    /* Get/set system time */
  345.   U, U, U, U, U, U,
  346.   /* 21 */ i_21,        /* DOS Services */
  347.   U, U, U, U, U, U, U, U, U, U, U, U, U, U, U,
  348.   /* 31 */ i_31,        /* DPMIsim */
  349.   U,
  350.   /* 33 */ i_33            /* Mouse */
  351. };
  352. #undef U
  353. #define NUM_EXCEPTIONS    (sizeof(exception_handler_list)/sizeof(exception_handler_list[0]))
  354.  
  355. exception_handler(void)
  356. {
  357.   int i;
  358.   if (topline_info)
  359.   {
  360.     char buf[20];
  361.     if (tss_ptr->tss_irqn == 14)
  362.       sprintf(buf, "0x%08lx", tss_ptr->tss_cr2 - ARENA);
  363.     else
  364.       sprintf(buf, "0x%08lx", tss_ptr->tss_eip);
  365.     for (i=0; buf[i]; i++)
  366.       poke(screen_seg, i*2+80, buf[i] | 0x0600);
  367.   }
  368.   i = tss_ptr->tss_irqn;
  369. /*  printf("i=%#02x\n", i); */
  370.   if (((i >= hard_slave_lo)  && (i <= hard_slave_hi)
  371.        && (i != hard_slave_lo + 5))
  372.       || ((i >= hard_master_lo) && (i <= hard_master_hi)))
  373.   {
  374.     in_hardware_interrupt = 1;
  375.     intr(i, &r);
  376.     in_hardware_interrupt = 0;
  377.     if (ctrl_break_hit)
  378.       return 1;
  379.     if (i == hard_master_lo + 1)
  380.     {
  381.       if (ctrl_c_causes_break)
  382.       {
  383.         r.r_ax = 0x0100;
  384.         intr(0x16, &r);
  385.         if (!(r.r_flags & 0x40) && (r.r_ax == 0x2e03))
  386.         {
  387.           _AH = 0;
  388.           geninterrupt(0x16);
  389.           ctrl_c_flag = 1;
  390.         }
  391.       }
  392.     }
  393.     if (ctrl_c_flag)
  394.     {
  395.       ctrl_c_flag = 0;
  396.       if (ctrl_c_causes_break)
  397.         return 1;
  398.     }
  399.     return 0;
  400.   }
  401.   if (i < NUM_EXCEPTIONS)
  402.     return (exception_handler_list[i])();
  403.   else
  404.     return 1;
  405. }
  406.  
  407. void retrieve_string(word32 v, char *transfer_buffer, char tchar)
  408. {
  409.   int i;
  410.   if (!use_DPMI) {
  411. #if 0
  412.     for (i=0; i<4096; i++)
  413.     {
  414.       c = peek8(v);
  415.       v++;
  416.       transfer_buffer[i] = c;
  417.       if (c == tchar)
  418.         break;
  419.     }
  420. #else
  421.     memscan32(v, transfer_buffer, tchar);
  422. #endif
  423.     return;
  424.   } else {
  425.     i = Pmemscan(tss_ptr->tss_ds, v, tchar, 4096);
  426.     if (i == 0) i = 4096;
  427.     Pmemget(tss_ptr->tss_ds, v, transfer_buffer, i);
  428.     return;
  429.   }
  430. }
  431.  
  432. generic_handler(void)
  433. {
  434.   tss2reg(&r);
  435.   intr(tss_ptr->tss_irqn, &r);
  436.   reg2tss_short(&r);            /* KJB */
  437.   return 0;
  438. }
  439.  
  440. i_10(void)
  441. {
  442.   word32 v;
  443.   word16 i, j;
  444.  
  445. /* CB changes */
  446. /* OLD:
  447.  * switch((word16)(tss_ptr->tss_eax) & 0xFF00) {
  448.  *   case 0xFD00:
  449.  *     graphics_pageflip();
  450.  *     return 0;
  451.  *   case 0xFE00:
  452.  *     graphics_inquiry();
  453.  *     return 0;
  454.  *   case 0xFF00:
  455.  *     graphics_mode((word16)(tss_ptr->tss_eax) & 0xff);
  456.  *     in_graphics_mode = (peekb(0x40, 0x49) > 7);
  457.  *     return 0;
  458.  * }
  459.  */
  460.   if(((word16)tss_ptr->tss_eax & 0xff00) >= gr_assist_func_start) {
  461.     graphics_assist();
  462.     in_graphics_mode = (peekb(0x40, 0x49) > 7);
  463.     return 0;
  464.   }
  465. /* end CB changes */
  466.  
  467.   tss2reg(&r);
  468.   i = (word16)tss_ptr->tss_eax; /* int10 function 0x11 subfunctions 0 & 0x10 */
  469.   if(i==0x1100 || i==0x1110) 
  470.   { /* user-defined text characters */
  471.     v = tss_ptr->tss_edx + ARENA; /* bh*cx bytes starting at (ds:dx) */
  472.     CHECK_SEGFAULT(v);
  473.     j = ((tss_ptr->tss_ebx >> 8) & 0xff) * ((word16)tss_ptr->tss_ecx);
  474.     memget(v, transfer_buffer, j);
  475.     r.r_dx = FP_OFF(transfer_buffer);
  476.     r.r_ds = _DS;
  477.     intr(0x10, &r);
  478.     reg2tss(&r);
  479.     tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
  480.     return 0;
  481.   }
  482.  
  483.   /* KJB - All unknown interrupts fall through to here (VESA VBE interrupts are
  484.    * one set) and we use the reg2tss_short() routine to copy the registers
  485.    * without sign extension so that we dont trash registers that the
  486.    * application is not expecting to be changed. Note also that I moved the
  487.    * code to change EBP into the above routine where it belongs.
  488.    */
  489.  
  490.   intr(0x10, &r);
  491.   reg2tss_short(&r);
  492.   if (i == 0x1130)
  493.     tss_ptr->tss_ebp = r.r_es * 16L + r.r_bp + 0xe0000000L;
  494.   return 0;
  495. }
  496.  
  497. #include "eventque.h"
  498.  
  499. #define  MSDRAW_STACK  128              /* stack size for mouse callback */
  500.  
  501. static word32  mousedraw_func32;        /* 32-bit mouse cursor drawing function */
  502. static word32  mousedraw_contaddr;      /* jump to this address after mouse draw */
  503. static char    mousedraw_active;        /* set while drawing mouse cursor */
  504. EventQueue    *event_queue = NULL;      /* event queue */
  505. typedef int far (*FFUNC)(void);
  506. static FFUNC   mousedraw_callback = 0;    /* DPMI real mode callback to prot */
  507.  
  508. static void mousedraw_hook(void)
  509. {
  510.   disable();
  511.   if(!mousedraw_active)
  512.   {
  513.     mousedraw_active = 1;
  514.     if(use_DPMI)
  515.     {
  516.       mousedraw_callback();
  517.       mousedraw_active = 0;
  518.     }
  519.     else
  520.     {
  521.       mousedraw_contaddr = a_tss.tss_eip;
  522.       a_tss.tss_eip = mousedraw_func32;
  523.     }
  524.   }
  525.   enable();
  526. }
  527.  
  528. i_33(void)
  529. {
  530.   void (*msdrawfun)(void);
  531.   int  queuesize;
  532.  
  533.   if(tss_ptr->tss_eax == 0x00ff) {
  534.     if(event_queue != NULL) {
  535.       EventQueueDeInit();
  536.       event_queue = NULL;
  537.     }
  538.     if((queuesize = (int)tss_ptr->tss_ebx) > 0) {
  539.       mousedraw_func32 = tss_ptr->tss_ecx;
  540.       mousedraw_active = 0;
  541.       msdrawfun = (mousedraw_func32 != 0L) ? mousedraw_hook : NULL;
  542.       if(use_DPMI) {
  543.         if(tss_ptr->tss_edx != 0x12345678L) return(0);    /* make sure V1.03 or more */
  544.         mousedraw_callback = (FFUNC)mousedraw_func32;
  545.       }
  546.       event_queue = EventQueueInit(queuesize, MSDRAW_STACK, msdrawfun);
  547.       if(event_queue != NULL) {
  548.         tss_ptr->tss_ebx =
  549.           (((word32)FP_SEG(event_queue)) << 4) +
  550.           ((word32)FP_OFF(event_queue)) +
  551.           0xe0000000L;
  552.         tss_ptr->tss_ecx =
  553.           (((word32)FP_SEG(&mousedraw_contaddr)) << 4) +
  554.           ((word32)FP_OFF(&mousedraw_contaddr)) +
  555.           0xe0000000L;
  556.         tss_ptr->tss_edx =
  557.           (((word32)FP_SEG(&mousedraw_active)) << 4) +
  558.           ((word32)FP_OFF(&mousedraw_active)) +
  559.           0xe0000000L;
  560.       }
  561.       else tss_ptr->tss_ebx = 0L;
  562.     }
  563.     tss_ptr->tss_eax = 0x0ff0;              /* acknowledge event handling */
  564.     return(0);
  565.   }
  566.   if (*((unsigned far *)0x000000CEL) == 0)
  567.     return 0;
  568.   r.r_ax = (word16)(tss_ptr->tss_eax);
  569.   r.r_bx = (word16)(tss_ptr->tss_ebx);
  570.   r.r_cx = (word16)(tss_ptr->tss_ecx);
  571.   r.r_dx = (word16)(tss_ptr->tss_edx);
  572.   intr(0x33, &r);
  573.   tss_ptr->tss_eax = r.r_ax;
  574.   tss_ptr->tss_ebx = r.r_bx;
  575.   tss_ptr->tss_ecx = r.r_cx;
  576.   tss_ptr->tss_edx = r.r_dx;
  577.   return 0;
  578. }
  579.  
  580. /*1.07 TSS last_tss; */
  581.  
  582. i_21(void)
  583. {
  584.   word32 v, trans_total, countleft;
  585.   int i, c, ah, tchar, trans_count;
  586.   char *cp;
  587.   tss2reg(&r);
  588.   ah = ((word16)(tss_ptr->tss_eax) >> 8) & 0xff;
  589.  
  590.   if (ah & 0x80) switch (ah)
  591.   {
  592.     case 0xfe:
  593.       return external_debugger_handler();
  594.     case 0xff:
  595.       return turbo_assist();
  596.     default:
  597.       return 1;
  598.   }
  599.   else switch (ah)
  600.   {
  601.     case 0x42: /* seek */
  602.       _openfd[r.r_bx] &= 0xfdff; /* clear EOF */
  603.       /* fall through */
  604.     case 0x01: /* read with echo */
  605.     case 0x02: /* con output */
  606.     case 0x03: /* aux input */
  607.     case 0x04: /* aux output */
  608.     case 0x05: /* prn output */
  609.     case 0x06: /* direct con i/o */
  610.     case 0x07: /* direct con input */
  611.     case 0x08: /* kbd read */
  612.     case 0x0b: /* kbd status */
  613.     case 0x0d: /* reset disk */
  614.     case 0x0e: /* select disk */
  615.     case 0x18: /* return al=0 */
  616.     case 0x19: /* get disk */
  617.     case 0x1d: /* return al=0 */
  618.     case 0x1e: /* return al=0 */
  619.     case 0x20: /* return al=0 */
  620.     case 0x2a: /* get date */
  621.     case 0x2b: /* set date */
  622.     case 0x2c: /* get time */
  623.     case 0x2d: /* set time */
  624.     case 0x2e: /* (re)set verify flag */
  625.     case 0x30: /* get version */
  626.     case 0x36: /* get disk free space */
  627.     case 0x37: /* get/set switch char */
  628.     case 0x4d: /* get return code */
  629.     case 0x54: /* get verify flag */
  630.     case 0x57: /* get/set file time stamp */
  631.     case 0x58: /* get/set UMB link state */
  632.     case 0x5c: /* file locking */
  633.     case 0x66: /* get/set global code page */
  634.     case 0x67: /* set handle count */
  635.     case 0x68: /* commit (flush and update directory) */
  636.       intr(0x21, &r);
  637.       reg2tss(&r);
  638.       return 0;
  639.     case 0x38: /* get country info */
  640.       r.r_ds = _DS;
  641.       r.r_dx = FP_OFF(transfer_buffer);
  642.       intr(0x21, &r);
  643.       if (r.r_flags & 1) 
  644.       {
  645.         tss_ptr->tss_eflags |= 1;
  646.         tss_ptr->tss_eax = r.r_ax;
  647.         return 0;
  648.       }
  649.       memput(tss_ptr->tss_edx + ARENA, transfer_buffer, 34);
  650.       return 0;
  651.     case 0x33: /* ^C checking and more */
  652.       switch (r.r_ax & 0xff) 
  653.       {
  654.       case 0x01: /* set ^C */
  655.       case 0x02: /* set extended ^C */
  656.     ctrl_c_causes_break = r.r_dx & 0xff;
  657.     /* fall through */
  658.       case 0x00: /* get ^C */
  659.       case 0x05: /* get boot drive */
  660.       case 0x06: /* get true dos version */
  661.     intr(0x21, &r);
  662.     reg2tss(&r);
  663.     return 0;
  664.       default:
  665.     return 1;
  666.       }
  667.     case 0x3e: /* close */
  668.       if (using_external_debugger && r.r_bx < 2)
  669.         return 0;
  670.       if (r.r_bx == 1)
  671.         redir_1_mono = 0;
  672.       if (r.r_bx == 2)
  673.         redir_2_mono = 0;
  674.       intr(0x21, &r);
  675.       reg2tss(&r);
  676.       return 0;
  677.     case 9: /* print string */
  678.     case 0x39: /* mkdir */
  679.     case 0x3a: /* rmdir */
  680.     case 0x3b: /* chdir */
  681.     case 0x41: /* unlink (delete) */
  682.     case 0x43: /* chmod */
  683.       if (ah == 9)
  684.         tchar = '$';
  685.       else
  686.         tchar = 0;
  687.       v = tss_ptr->tss_edx + ARENA;
  688.       CHECK_SEGFAULT(v);
  689.       retrieve_string(v, transfer_buffer, tchar);
  690.       r.r_dx = FP_OFF(transfer_buffer);
  691.       r.r_ds = _DS;
  692.       intr(0x21, &r);
  693.       reg2tss(&r);
  694.       return 0;
  695.     case 0x3c: /* creat (rewrite) */
  696.       v = tss_ptr->tss_edx + ARENA;
  697.       CHECK_SEGFAULT(v);
  698.       retrieve_string(v, transfer_buffer, 0);
  699.       i = _creat(transfer_buffer, (int)(tss_ptr->tss_ecx));
  700.       if (i < 0)
  701.       {
  702.         tss_ptr->tss_eax = errno;
  703.         tss_ptr->tss_eflags |= 1;
  704.       }
  705.       else
  706.       {
  707.         tss_ptr->tss_eax = i;
  708.         tss_ptr->tss_eflags &= ~1;
  709.       }
  710.       return 0;
  711.     case 0x3d: /* open */
  712.       v = tss_ptr->tss_edx + ARENA;
  713.       CHECK_SEGFAULT(v)
  714.       retrieve_string(v, transfer_buffer, 0);
  715.       i = (word16)(tss_ptr->tss_eax) & 0xf0;
  716.       if (tss_ptr->tss_eax & O_WRONLY) i |= 1;
  717.       if (tss_ptr->tss_eax & O_RDWR) i |= 2;
  718.       i = _open(transfer_buffer, i);
  719.       if (i < 0)
  720.       {
  721.         tss_ptr->tss_eax = errno;
  722.         tss_ptr->tss_eflags |= 1;
  723.       }
  724.       else
  725.       {
  726.         tss_ptr->tss_eax = i;
  727.         tss_ptr->tss_eflags &= ~1;
  728.       }
  729.       return 0;
  730.     case 0x1a: /* set dta */
  731.       user_dta = tss_ptr->tss_edx;
  732.       setdta((char far *)transfer_buffer);
  733.       return 0;
  734.     case 0x2f: /* get dta */
  735.       tss_ptr->tss_ebx = user_dta;
  736.       return 0;
  737.     case 0x56: /* rename/move */
  738.       v = tss_ptr->tss_edx + ARENA;
  739.       CHECK_SEGFAULT(v)
  740.       retrieve_string(v, transfer_buffer, 0);
  741.       i = strlen(transfer_buffer) + 1;
  742.       r.r_dx = FP_OFF(transfer_buffer);
  743.       r.r_ds = _DS;
  744.       v = tss_ptr->tss_edi + ARENA;
  745.       retrieve_string(v, transfer_buffer+i, 0);
  746.       r.r_di = FP_OFF(transfer_buffer)+i;
  747.       r.r_es = _DS;
  748.       intr(0x21, &r);
  749.       tss_ptr->tss_eax = r.r_ax;
  750.       tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  751.       return 0;
  752.     case 0x3f: /* read */
  753.       if (!tss_ptr->tss_edx) {
  754.         fprintf(stderr, "This image has a buggy read.s module.  Run DPMIFIX on it and try again.\n");
  755.         return 1;
  756.       }
  757.       if (tss_ptr->tss_edx == transfer_linear)
  758.       {
  759.         i = read(r.r_bx, transfer_buffer, r.r_cx);
  760.         if (i<0)
  761.         {
  762.           tss_ptr->tss_eflags |= 1; /* carry */
  763.           tss_ptr->tss_eax = _doserrno;
  764.         }
  765.         else
  766.         {
  767.           tss_ptr->tss_eflags &= ~1;
  768.           tss_ptr->tss_eax = i;
  769.         }
  770.         return 0;
  771.       }
  772.       trans_total = 0;
  773.       countleft = tss_ptr->tss_ecx;
  774.       v = tss_ptr->tss_edx;
  775.       CHECK_SEGFAULT(v+ARENA)
  776.       while (countleft > 0)
  777.       {
  778.         trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
  779.         i = read(r.r_bx, transfer_buffer, trans_count);
  780.         if (i < 0)
  781.         {
  782.           tss_ptr->tss_eflags |= 1; /* carry */
  783.           tss_ptr->tss_eax = _doserrno;
  784.           return 0;
  785.         }
  786.         memput(v+ARENA, transfer_buffer, i);
  787.         trans_total += i;
  788.         v += i;
  789.         countleft -= i;
  790.         if (isatty(r.r_bx) && (i<trans_count))
  791.           break; /* they're line buffered */
  792.         if (i == 0)
  793.           break;
  794.       }
  795.       tss_ptr->tss_eax = trans_total;
  796.       tss_ptr->tss_eflags &= ~1;
  797.       return 0;
  798.     case 0x40: /* write */
  799.       if (tss_ptr->tss_edx == transfer_linear)
  800.       {
  801.         if ((r.r_bx == 1) && redir_1_mono)
  802.           i = mono_write(transfer_buffer, r.r_cx);
  803.         else if ((r.r_bx == 2) && redir_2_mono)
  804.           i = mono_write(transfer_buffer, r.r_cx);
  805.         else
  806.         {
  807.           int fd = r.r_bx;
  808.           if (r.r_cx == 0) /* for ftruncate */
  809.             i = _write(fd, transfer_buffer, r.r_cx);
  810.           else
  811.             i = write(fd, transfer_buffer, r.r_cx);
  812.         }
  813.         if (i<0)
  814.         {
  815.           tss_ptr->tss_eflags |= 1; /* carry */
  816.           tss_ptr->tss_eax = _doserrno;
  817.         }
  818.         else
  819.         {
  820.           tss_ptr->tss_eflags &= ~1;
  821.           tss_ptr->tss_eax = i;
  822.         }
  823.         return 0;
  824.       }
  825.       trans_total = 0;
  826.       countleft = tss_ptr->tss_ecx;
  827.       if (countleft == 0)
  828.       {
  829.         r.r_ax = 0x4000;
  830.         r.r_cx = 0;
  831.         intr(0x21,&r);
  832.         tss_ptr->tss_eax = 0;
  833.         tss_ptr->tss_eflags &= ~1;
  834.         return 0;
  835.       }
  836.       v = tss_ptr->tss_edx;
  837.       CHECK_SEGFAULT(v+ARENA);
  838.       r.r_dx = (int)transfer_buffer;
  839.       while (countleft > 0)
  840.       {
  841.         trans_count = (word16)((countleft <= 4096) ? countleft : 4096);
  842.         memget(v+ARENA, transfer_buffer, trans_count);
  843.         if ((r.r_bx == 1) && redir_1_mono)
  844.           i = mono_write(transfer_buffer, trans_count);
  845.         else if ((r.r_bx == 2) && redir_2_mono)
  846.           i = mono_write(transfer_buffer, trans_count);
  847.         else
  848.         {
  849.           int fd = r.r_bx;
  850.           i = write(fd, transfer_buffer, trans_count);
  851.           if (in_graphics_mode && (fd < 3))
  852.           {
  853.             word32 far *p = graphics_pt;
  854.             for (c = 0; c < 256; c++)
  855.               *p++ &= ~PT_P;
  856.           }
  857.         }
  858.         if (i<0) /* carry */
  859.         {
  860.           tss_ptr->tss_eflags |= 1; /* carry */
  861.           tss_ptr->tss_eax = _doserrno;
  862.           return 0;
  863.         }
  864.         trans_total += i;
  865.         v += i;
  866.         countleft -= i;
  867.         if (i < trans_count)
  868.           break;
  869.       }
  870.       tss_ptr->tss_eax = trans_total;
  871.       tss_ptr->tss_eflags &= ~1;
  872.       return 0;
  873.     case 0x44: /* ioctl */
  874.       return i_21_44();
  875.     case 0x45: /* dup */
  876.       i = _openfd[r.r_bx];
  877.       intr(0x21, &r);
  878.       if (!(r.r_flags & 1))
  879.         _openfd[r.r_ax] = i;
  880.       reg2tss(&r);
  881.       return 0;
  882.     case 0x46: /* dup2 */
  883.       i = _openfd[r.r_bx];
  884.       c = r.r_cx;
  885.       intr(0x21, &r);
  886.       if (!(r.r_flags & 1))
  887.         _openfd[c] = i;
  888.       reg2tss(&r);
  889.       return 0;
  890.     case 0x4e: /* find first */
  891.       CHECK_SEGFAULT(user_dta+ARENA);
  892.       v = tss_ptr->tss_edx + ARENA;
  893.       CHECK_SEGFAULT(v);
  894.       retrieve_string(v, transfer_buffer+43, 0);
  895.       r.r_dx = FP_OFF(transfer_buffer+43);
  896.       r.r_ds = _DS;
  897.       intr(0x21, &r);
  898.       reg2tss(&r);
  899.       for (i=20; i>=0; i--)
  900.         transfer_buffer[i+28] = transfer_buffer[i+26];
  901.       transfer_buffer[32+13] = 0; /* asciiz termination */
  902.       memput(user_dta+ARENA, transfer_buffer, 48);
  903.       return 0;
  904.     case 0x4f: /* find next */
  905.       CHECK_SEGFAULT(user_dta+ARENA);
  906.       memget(user_dta+ARENA, transfer_buffer, 48);
  907.       for (i=0; i<=20; i++)
  908.         transfer_buffer[i+26] = transfer_buffer[i+28];
  909.       intr(0x21, &r);
  910.       reg2tss(&r);
  911.       for (i=20; i>=0; i--)
  912.         transfer_buffer[i+28] = transfer_buffer[i+26];
  913.       transfer_buffer[32+13] = 0; /* asciiz termination */
  914.       memput(user_dta+ARENA, transfer_buffer, 48);
  915.       return 0;
  916.     case 0x47: /* getwd */
  917.       getcurdir((int)(tss_ptr->tss_edx & 0xff), transfer_buffer);
  918.       for (cp=transfer_buffer; *cp; cp++)
  919.       {
  920.         if (*cp == '\\') *cp = '/';
  921.         *cp = tolower(*cp);
  922.       }
  923.       memput(tss_ptr->tss_esi+ARENA, transfer_buffer, strlen(transfer_buffer)+1);
  924.       tss_ptr->tss_eax = (unsigned)r.r_ax;
  925.       tss_ptr->tss_eflags &= ~1;
  926.       return 0;
  927.     case 0x4a: /* sbrk/brk -- NOT ORGINAL MEANING */
  928.       if (tss_ptr->tss_eax & 0xff)
  929.         tss_ptr->tss_eax = paging_sbrk(tss_ptr->tss_ebx);
  930.       else
  931.         tss_ptr->tss_eax = paging_brk(tss_ptr->tss_ebx);
  932.       return 0;
  933.     case 0x4c: /* exit */
  934.       if (using_external_debugger && (tss_ptr == &a_tss))
  935.         return 1;
  936.       else
  937.         exit((word8)(tss_ptr->tss_eax));
  938.     default:
  939.       return 1;
  940.   }
  941. }
  942.  
  943. static int reg2gate(word32 r)
  944. {
  945.   int g = (int)(r & 0xff);
  946.   if (g >= 0x08 && g <= 0x0f)
  947.     g = g - 0x08 + hard_master_lo;
  948.   else if (g >= 0x70 && g <= 0x77)
  949.     g = g - 0x70 + hard_slave_lo;
  950.   return g;
  951. }
  952.  
  953. static int dpmisim_is_exec = 0;
  954.  
  955. int i_31(void)
  956. {
  957.   int gate, i;
  958.   word16 far *fptr;
  959.   word16 dpmisim_spare_stack[128];
  960.   union REGS r;
  961.   struct SREGS s;
  962.   switch ((word16)(tss_ptr->tss_eax))
  963.   {
  964.     case 0x0100:
  965.       r.h.ah = 0x48;
  966.       r.x.bx = (word16)tss_ptr->tss_ebx;
  967.       int86(0x21, &r, &r);
  968.       if ((r.x.flags & 1) && ((word16)tss_ptr->tss_ebx != 0xffff))
  969.       {
  970.         valloc_shrink_rmem(((word16)tss_ptr->tss_ebx)/256 + 1);
  971.         r.h.ah = 0x48;
  972.         r.x.bx = (word16)tss_ptr->tss_ebx;
  973.         int86(0x21, &r, &r);
  974. /*        if (r.x.flags & 1)
  975.           printf("biggest after shrinking is %04x\n", r.x.bx); */
  976.       }
  977.       tss_ptr->tss_eflags &= ~1;
  978.       tss_ptr->tss_eflags |= r.x.flags & 1;
  979.       tss_ptr->tss_edx =
  980.       tss_ptr->tss_eax = r.x.ax;
  981.       tss_ptr->tss_ebx = r.x.bx;
  982. /*      printf("allocated %x, %d %x\n", r.x.ax, r.x.flags & 1, r.x.bx); */
  983.       return 0;
  984.  
  985.     case 0x0101:
  986.       r.h.ah = 0x49;
  987.       s.es = (word16)tss_ptr->tss_edx;
  988.       int86x(0x21, &r, &r, &s);
  989. /*      printf("released %x, %d %x\n", (word16)tss_ptr->tss_edx, r.x.flags & 1, r.x.ax); */
  990.       return 0;
  991.  
  992.     case 0x0102:
  993.       r.h.ah = 0x4a;
  994.       r.x.bx = (word16)tss_ptr->tss_ebx;
  995.       s.es = (word16)tss_ptr->tss_edx;
  996.       int86x(0x21, &r, &r, &s);
  997.       tss_ptr->tss_eflags &= ~1;
  998.       tss_ptr->tss_eflags |= r.x.flags & 1;
  999.       tss_ptr->tss_eax = r.x.ax;
  1000.       tss_ptr->tss_ebx = r.x.bx;
  1001.       return 0;
  1002.  
  1003.     case 0x0200:
  1004. /*      gate = (word8)tss_ptr->tss_ebx; */
  1005.       gate = reg2gate(tss_ptr->tss_ebx);
  1006.       tss_ptr->tss_ecx = peek(0, gate*4+2);
  1007.       tss_ptr->tss_edx = peek(0, gate*4);
  1008.       tss_ptr->tss_eflags &= ~1;
  1009.       return 0;
  1010.  
  1011.     case 0x0201:
  1012. /*      gate = (word8)tss_ptr->tss_ebx; */
  1013.       gate = reg2gate(tss_ptr->tss_ebx);
  1014.       disable();
  1015.       poke(0, gate*4+2, tss_ptr->tss_ecx);
  1016.       poke(0, gate*4, tss_ptr->tss_edx);
  1017.       enable();
  1018.       tss_ptr->tss_eflags &= ~1;
  1019.       return 0;
  1020.  
  1021.     case 0x0204:
  1022.       gate = reg2gate(tss_ptr->tss_ebx);
  1023.       tss_ptr->tss_ecx = idt[gate].selector;
  1024.       tss_ptr->tss_edx = idt[gate].offset0 | (idt[gate].offset1 << 16);
  1025.       tss_ptr->tss_eflags &= ~1;
  1026.       return 0;
  1027.  
  1028.     case 0x0205:
  1029.       gate = reg2gate(tss_ptr->tss_ebx);
  1030.       idt[gate].selector = (word16)(tss_ptr->tss_ecx);
  1031.       idt[gate].offset0 = (word16)(tss_ptr->tss_edx);
  1032.       idt[gate].offset1 = (word16)(tss_ptr->tss_edx >> 16);
  1033.       idt[gate].stype = 0x8e00;
  1034.       tss_ptr->tss_eflags &= ~1;
  1035.       return 0;
  1036.  
  1037.     case 0x0300:
  1038.     case 0x0301:
  1039.     case 0x0302:
  1040.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1041.       if ((word16)tss_ptr->tss_ecx)
  1042.       {
  1043.         tss_ptr->tss_eax = 0x8021;
  1044.         tss_ptr->tss_eflags |= 1;
  1045.         return 0;
  1046.       }
  1047.       memget(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
  1048.  
  1049.       if (dpmisim_regs[24] == 0)
  1050.       {
  1051.         dpmisim_regs[24] = _SS;
  1052.         dpmisim_regs[23] = (word16)(dpmisim_spare_stack) + sizeof(dpmisim_spare_stack);
  1053.       }
  1054.       if ((word16)tss_ptr->tss_eax != 0x0301)
  1055.       {
  1056.         dpmisim_regs[23] -= 2;    /* fake pushing flags on stack */
  1057.         fptr = MK_FP(dpmisim_regs[24], dpmisim_regs[23]);
  1058.         *fptr = dpmisim_regs[16];
  1059.       }
  1060.  
  1061.       if ((word16)tss_ptr->tss_eax == 0x0300)
  1062.       {
  1063.         dpmisim_regs[21] = peek(0, (word8)tss_ptr->tss_ebx * 4);
  1064.         dpmisim_regs[22] = peek(0, (word8)tss_ptr->tss_ebx * 4 + 2);
  1065.       }
  1066.  
  1067.       if (dpmisim_is_exec)
  1068.       {
  1069.         word32 our_interrupt_table[256];
  1070.         page_out_everything();
  1071.         movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
  1072.         uninit_controllers();
  1073.         dpmisim();
  1074.         init_controllers();
  1075.         ctrl_break_hit = 0;
  1076.         disable();
  1077.         movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
  1078.         enable();
  1079.        page_in_everything();
  1080.       }
  1081.       else
  1082.         dpmisim();
  1083.  
  1084.       memput(tss_ptr->tss_edi + ARENA, dpmisim_regs, 50);
  1085.       tss_ptr->tss_eflags &= ~1;
  1086.       return 0;
  1087.  
  1088.     case 0x0303:
  1089.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1090.       for (i=0; i<16; i++)
  1091.         if (dpmisim_rmcb[i].cb_address == 0)
  1092.           break;
  1093.       if (i == 16)
  1094.       {
  1095.         tss_ptr->tss_eflags |= 1;
  1096.         tss_ptr->tss_eax = 0x8015;
  1097.         return 0;
  1098.       }
  1099.       dpmisim_rmcb[i].cb_address = tss_ptr->tss_esi;
  1100.       dpmisim_rmcb[i].reg_ptr = tss_ptr->tss_edi;
  1101.       tss_ptr->tss_eflags &= ~1;
  1102.       tss_ptr->tss_ecx = _CS;
  1103.       tss_ptr->tss_edx = (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0);
  1104.       return 0;
  1105.  
  1106.     case 0x0304:
  1107.       if ((word16)tss_ptr->tss_ecx == _CS)
  1108.         for (i=0; i<16; i++)
  1109.           if ((word16)tss_ptr->tss_edx == (word16)dpmisim_rmcb0 + i * ((word16)dpmisim_rmcb1 - (word16)dpmisim_rmcb0))
  1110.           {
  1111.             dpmisim_rmcb[i].cb_address = 0;
  1112.             tss_ptr->tss_eflags &= ~1;
  1113.             return 0;
  1114.           }
  1115.       tss_ptr->tss_eflags |= 1;
  1116.       tss_ptr->tss_eax = 0x8024;
  1117.       return 0;
  1118.       
  1119.     case 0x0500:
  1120.       CHECK_SEGFAULT(tss_ptr->tss_edi + ARENA);
  1121.       memset(transfer_buffer, 0xff, 48);
  1122.       ((word32 *)transfer_buffer)[8] = dalloc_max_size();
  1123.       ((word32 *)transfer_buffer)[4] =
  1124.       ((word32 *)transfer_buffer)[6] = valloc_max_size();
  1125.       ((word32 *)transfer_buffer)[2] =
  1126.       ((word32 *)transfer_buffer)[5] = valloc_max_size() - valloc_used();
  1127.       ((word32 *)transfer_buffer)[1] = 
  1128.         ((word32 *)transfer_buffer)[5] + ((word32 *)transfer_buffer)[8] - dalloc_used();
  1129.       ((word32 *)transfer_buffer)[0] = ((word32 *)transfer_buffer)[1] * 4096L;
  1130.       memput(tss_ptr->tss_edi + ARENA, transfer_buffer, 48);
  1131.       tss_ptr->tss_eflags &= ~1;
  1132.       return 0;
  1133.  
  1134.     case 0x0600: /* These all deal with locking memory.  We ignore them for now, */
  1135.     case 0x0601: /* but allow them to succeed to that in real DPMI mode you can */
  1136.     case 0x0602: /* use them. */
  1137.     case 0x0603:
  1138.     case 0x0702:
  1139.     case 0x0703:
  1140.       tss_ptr->tss_eflags &= ~1;
  1141.       return 0;
  1142.  
  1143.     case 0x0604:
  1144.       tss_ptr->tss_ebx = 0;
  1145.       tss_ptr->tss_ecx = 4096;
  1146.       tss_ptr->tss_eflags &= ~1;
  1147.       return 0;
  1148.  
  1149.     default: /* mark as unsupported */
  1150.       tss_ptr->tss_eflags |= 1;
  1151.       tss_ptr->tss_eax = 0x8001;
  1152.       return 0;
  1153.   }
  1154. }
  1155.  
  1156. struct time32 {
  1157.   word32 secs;
  1158.   word32 usecs;
  1159. };
  1160.  
  1161. struct tz32 {
  1162.   word32 offset;
  1163.   word32 dst;
  1164. };
  1165.  
  1166. struct  stat32 {
  1167.         short st_dev;
  1168.         short st_ino;
  1169.         short st_mode;
  1170.         short st_nlink;
  1171.         short st_uid;
  1172.         short st_gid;
  1173.         short st_rdev;
  1174.         short st_align_for_word32;
  1175.         long  st_size;
  1176.         long  st_atime;
  1177.         long  st_mtime;
  1178.         long  st_ctime;
  1179.         long  st_blksize;
  1180. };
  1181.  
  1182. turbo_assist(void)
  1183. {
  1184.   word32 p1, p2, r;
  1185.   struct time32 time32;
  1186.   struct tz32 tz32;
  1187.   struct stat32 statbuf32;
  1188.   struct stat statbuf;
  1189.   int i;
  1190.   char buf[128], *bp;
  1191.   word32 our_interrupt_table[256];
  1192.  
  1193.   p1 = tss_ptr->tss_ebx;
  1194.   p2 = tss_ptr->tss_ecx;
  1195.   switch ((word8)(tss_ptr->tss_eax))
  1196.   {
  1197.     case 1: /* creat */
  1198.       retrieve_string(p1+ARENA, buf, 0);
  1199.       r = creat(buf, S_IREAD | S_IWRITE);
  1200.       break;
  1201.  
  1202.     case 2: /* open */
  1203.       retrieve_string(p1+ARENA, buf, 0);
  1204.       r = open(buf, (int)p2, S_IREAD | S_IWRITE);
  1205.       break;
  1206.  
  1207.     case 3: /* fstat */
  1208.       memset(&statbuf, 0, sizeof(statbuf));
  1209.       r = fstat((int)p1, &statbuf);
  1210.       statbuf32.st_dev = statbuf.st_dev;
  1211.       statbuf32.st_ino = statbuf.st_ino;
  1212.       statbuf32.st_mode = statbuf.st_mode;
  1213.       statbuf32.st_nlink = statbuf.st_nlink;
  1214.       statbuf32.st_uid = 42;
  1215.       statbuf32.st_gid = 42;
  1216.       statbuf32.st_rdev = statbuf.st_rdev;
  1217.       statbuf32.st_size = statbuf.st_size;
  1218.       statbuf32.st_atime = statbuf.st_atime;
  1219.       statbuf32.st_mtime = statbuf.st_mtime;
  1220.       statbuf32.st_ctime = statbuf.st_ctime;
  1221.       statbuf32.st_blksize = 4096;
  1222.       memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
  1223.       break;
  1224.  
  1225.     case 4: /* gettimeofday */
  1226.       if (p2)
  1227.       {
  1228.         CHECK_SEGFAULT(p2+ARENA);
  1229.         tz32.offset = timezone;
  1230.         tz32.dst = daylight;
  1231.         memput(p2+ARENA, &tz32, sizeof(tz32));
  1232.       }
  1233.       if (p1)
  1234.       {
  1235.         int dh;
  1236.         CHECK_SEGFAULT(p1+ARENA);
  1237.         time((long *)&(time32.secs));
  1238.         _AH = 0x2c;
  1239.         geninterrupt(0x21);
  1240.         dh = _DH;
  1241.         time32.usecs = _DL * 10000L;
  1242.         if (time32.secs % 60 != dh)
  1243.           time32.secs++;
  1244.         memput(p1+ARENA, &time32, sizeof(time32));
  1245.       }
  1246.       r = 0;
  1247.       break;
  1248.  
  1249.     case 5: /* settimeofday */
  1250.       if (p2)
  1251.       {
  1252.         CHECK_SEGFAULT(p2+ARENA);
  1253.         memget(p2+ARENA, &tz32, sizeof(tz32));
  1254.         timezone = tz32.offset;
  1255.         daylight = (int)tz32.dst;
  1256.       }
  1257.       if (p1)
  1258.       {
  1259.         CHECK_SEGFAULT(p1+ARENA);
  1260.         memget(p1+ARENA, &time32, sizeof(time32));
  1261.         stime((long *)&(time32.secs));
  1262.       }
  1263.       r = 0;
  1264.       break;
  1265.  
  1266.     case 6: /* stat */
  1267.       memset(&statbuf, 0, sizeof(statbuf));
  1268.       retrieve_string(p1+ARENA, transfer_buffer, 0);
  1269.       r = unixlike_stat(transfer_buffer, &statbuf);
  1270.       statbuf32.st_dev = statbuf.st_dev;
  1271.       statbuf32.st_ino = statbuf.st_ino;
  1272.       statbuf32.st_mode = statbuf.st_mode;
  1273.       statbuf32.st_nlink = statbuf.st_nlink;
  1274.       statbuf32.st_uid = statbuf.st_uid;
  1275.       statbuf32.st_gid = statbuf.st_gid;
  1276.       statbuf32.st_rdev = statbuf.st_rdev;
  1277.       statbuf32.st_size = statbuf.st_size;
  1278.       statbuf32.st_atime = statbuf.st_atime;
  1279.       statbuf32.st_mtime = statbuf.st_mtime;
  1280.       statbuf32.st_ctime = statbuf.st_ctime;
  1281.       statbuf32.st_blksize = 4096;
  1282.       memput(p2+ARENA, &statbuf32, sizeof(statbuf32));
  1283.       break;
  1284.  
  1285.     case 7: /* system */
  1286.       retrieve_string(p1+ARENA, transfer_buffer, 0);
  1287.       page_out_everything();
  1288.       movedata(0, 0, FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 256*4);
  1289.       uninit_controllers();
  1290.       sscanf(transfer_buffer, "%s%n", buf, &i);
  1291.       if (strpbrk(transfer_buffer, "<>|") == NULL)
  1292.         r = spawnlp(P_WAIT, buf, buf, transfer_buffer+i, 0);
  1293.       else
  1294.         r = -1;
  1295.       bp = buf+strlen(buf)-4;
  1296.       if (stricmp(bp, ".exe") && stricmp(bp, ".com") && (r & 0x80000000L))
  1297.         r = system(transfer_buffer);
  1298.       init_controllers();
  1299.       ctrl_break_hit = 0;
  1300.       disable();
  1301.       movedata(FP_SEG(our_interrupt_table), FP_OFF(our_interrupt_table), 0, 0, 256*4);
  1302.       enable();
  1303.       page_in_everything();
  1304.       break;
  1305.  
  1306.     case 8: /* _setmode() */
  1307.       _BX=(int)p1;
  1308.       _AX=0x4400;
  1309.       geninterrupt(0x21);
  1310.       i = _DX;
  1311.       if (p2 & O_BINARY)
  1312.         i |= 0x20;
  1313.       else
  1314.         i &= ~0x20;
  1315.       _BX=(int)p1;
  1316.       _DX = i;
  1317.       _AX=0x4401;
  1318.       geninterrupt(0x21);
  1319.       r = setmode((int)p1, (int)p2);
  1320.       break;
  1321.  
  1322.     case 9: /* chmod */
  1323.       retrieve_string(p1+ARENA, buf, 0);
  1324.       r = chmod(buf, (int)p2);
  1325.       break;
  1326.  
  1327.     case 10: /* DPMI exec */
  1328.       dpmisim_is_exec = 1;
  1329.       tss_ptr->tss_eax = 0x0300;
  1330.       i_31();
  1331.       dpmisim_is_exec = 0;
  1332.       return 0;
  1333.  
  1334.     default:
  1335.       return 1;
  1336.   }
  1337.   tss_ptr->tss_eflags &= ~1;
  1338.   if (r == -1)
  1339.   {
  1340.     tss_ptr->tss_eflags |= 1;
  1341.     tss_ptr->tss_eax = (errno == 35) ? 36 : errno;
  1342.     return 0;
  1343.   }
  1344.   tss_ptr->tss_eax = r;
  1345.   return 0;
  1346. }
  1347.  
  1348. i_21_44(void)
  1349. {
  1350.   switch ((word8)(tss_ptr->tss_eax))
  1351.   {
  1352.     case 0x00:
  1353.     case 0x01:
  1354.     case 0x06:
  1355.     case 0x07:
  1356.     case 0x08:
  1357.     case 0x09:
  1358.     case 0x0a:
  1359.     case 0x0b:
  1360.     case 0x0e:
  1361.     case 0x0f:
  1362.       intr(0x21, &r);
  1363.       tss_ptr->tss_edx = r.r_dx;
  1364.       tss_ptr->tss_eax = r.r_ax;
  1365.       tss_ptr->tss_eflags = flmerge(r.r_flags, tss_ptr->tss_eflags);
  1366.       return 0;
  1367.     default:
  1368.       return 1;
  1369.   }
  1370. }
  1371.